﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Xml;
using System.Collections;
using System.IO;
using System.Reflection;
using CustomerEmailer.Properties;
using CustomerEmailer.Common;
using System.Xml.Xsl;
using System.Xml.XPath;
using System.Xml.Linq;

namespace CustomerEmailer
{
    public partial class ExtendedTreeView : UserControl
    {
        List<TreeNode> node_list = new List<TreeNode>();
        Color[] colorArray = { Color.Red, Color.Blue, Color.HotPink, Color.Maroon, Color.Aqua, Color.DarkGray, Color.DarkGreen, Color.DarkOrange };
        Color prevColor = Color.Green, prevGrpColor = Color.Red;
        TreeNode callingNode;
        bool doneCheck=true;

        public ExtendedTreeView()
        {
            InitializeComponent();
            SetImages();
            treeView1.DragDrop += new DragEventHandler(treeView1_DragDrop);
            treeView1.DragEnter += new DragEventHandler(treeView1_DragEnter);
            treeView1.ItemDrag += new ItemDragEventHandler(treeView1_ItemDrag);
            treeView1.AfterCheck += new TreeViewEventHandler(treeView1_AfterCheck);

            treeView2.DragDrop += new DragEventHandler(treeView1_DragDrop);
            treeView2.DragEnter += new DragEventHandler(treeView1_DragEnter);
            treeView2.ItemDrag += new ItemDragEventHandler(treeView1_ItemDrag);
            treeView2.AfterCheck += new TreeViewEventHandler(treeView1_AfterCheck);
        }

        void SetImages()
        {
            treeView1.ImageList = new ImageList();
            treeView2.ImageList = new ImageList();
            var _assembly = Assembly.GetExecutingAssembly();

            Bitmap imgUsrGrp = Resources.UserGroup;
            Bitmap imgUsrInfo = Resources.UserInfo;
            Bitmap imgCursor = Resources.point;

            treeView1.ImageList.Images.Add("Cursor", imgCursor);
            treeView1.ImageList.Images.Add("ContactGrp", imgUsrGrp);
            treeView1.ImageList.Images.Add("Customers", imgUsrInfo);

            treeView2.ImageList.Images.Add("Cursor", imgCursor);
            treeView2.ImageList.Images.Add("ContactGrp", imgUsrGrp);
            treeView2.ImageList.Images.Add("Customers", imgUsrInfo);
        }

        List<TreeNode> treeNodes;
        public List<TreeNode> GetGroupNodes()
        {
            treeNodes = new List<TreeNode>();
            GetGroupNodes(selectedTreeView.Nodes);
            return treeNodes.Distinct().ToList();
        }

        private void GetGroupNodes(TreeNodeCollection treeNodeCollection)
        {
            foreach (TreeNode treeNode in treeNodeCollection)
            {
                if (treeNode.Nodes.Count > 0)
                {
                    GetGroupNodes(treeNode.Nodes);
                    ModifyTreeNodes(treeNodes, treeNode);
                }
                else
                {
                    ModifyTreeNodes(treeNodes, treeNode);
                }
            }
        }

        void ModifyTreeNodes(List<TreeNode> treeNodes, TreeNode treeNode)
        {
            /*if (treeNode.Tag == null)
            {
                treeNodes.Add(treeNode);
            }*/
            if (treeNode.ImageKey == "ContactGrp")
            {
                treeNodes.Add(treeNode);
            }
        }

        public void sort(TreeNode node)
        {
            foreach (TreeNode n in node.Nodes)
                sort(n);
            try
            {
                TreeNode temp = null;
                List<TreeNode> childs = new List<TreeNode>();
                while (node.Nodes.Count > 0)
                {
                    foreach (TreeNode n in node.Nodes)
                        if (temp == null || n.Text.CompareTo(temp.Text)<=0)
                            temp = n;
                    node.Nodes.Remove(temp);
                    childs.Add(temp);
                    temp = null;
                }
                node.Nodes.Clear();
                foreach (TreeNode a in childs)
                    node.Nodes.Add(a);
            }
            catch { }
        }

        public void InitalizeTreeNode(string fileName)
        {
            /*try
            {*/
                // SECTION 1. Create a DOM Document and load the XML data into it.
                XmlDocument dom = new XmlDocument();
                dom.Load(Utils.GetXmlFileLocation(fileName));
            
/*                System.Text.StringBuilder sortedXml = new System.Text.StringBuilder();
                XmlWriterSettings settings = new XmlWriterSettings();
                settings.Indent = false;
                XmlWriter writer = XmlWriter.Create(sortedXml, settings);

                XslCompiledTransform sortXsl = new XslCompiledTransform();
                sortXsl.Load(Utils.GetXmlFileLocation("customers.xslt"));
                sortXsl.Transform(dom, writer);
                writer.Close();
                dom.LoadXml(sortedXml.ToString());
                */
                // SECTION 2. Initialize the TreeView control.
                treeView1.Nodes.Clear();


                treeView1.Nodes.Add(new TreeNode(dom.DocumentElement.Attributes["name"].Value));
                TreeNode tNode = new TreeNode();
                tNode = treeView1.Nodes[0]; 
                tNode.ImageKey = "ContactGrp";

                // SECTION 3. Populate the TreeView with the DOM nodes.
                AddNode(dom.DocumentElement, tNode);
                //treeView1.ExpandAll();
                foreach (TreeNode node in treeView1.Nodes)
                    sort(node);

                colorNodes(treeView1.Nodes);
            /*}
            catch (XmlException xmlEx)
            {
                MessageBox.Show(xmlEx.Message);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }*/
        }

        private void colorNodes(TreeNodeCollection nodes)
        {
            foreach (TreeNode node in nodes)
            {
                if (node.ImageKey == "ContactGrp")
                {
                    colorNodes(node.Nodes);
                    Color current = Color.Red;
                    while (current == prevGrpColor)
                        current = colorArray[new Random().Next(colorArray.Length)];
                    node.ForeColor = current;
                    prevGrpColor = current;
                }
                else if (node.ImageKey == "Customers")
                {
                    Color current = Color.Green;
                    while (current == prevColor)
                        current = colorArray[new Random().Next(colorArray.Length)];
                    node.ForeColor = current;
                    prevColor = current;
                }
            }
        }

        private void AddNode(XmlNode inXmlNode, TreeNode inTreeNode)
        {
            XmlNode xNode;
            TreeNode tNode;
            XmlNodeList nodeList;
            int i;

            nodeList = inXmlNode.ChildNodes;
            for (i = 0; i <= nodeList.Count - 1; i++)
            {
                xNode = inXmlNode.ChildNodes[i];
                TreeNode node = new TreeNode();

                if (xNode.Name=="customer")
                {
                    node.Text = xNode.Attributes["name"].Value;
                    node.ToolTipText = xNode.Attributes["detail"].Value;
                    node.Tag = xNode.Attributes["cell"].Value + "#" + xNode.Attributes["office"].Value + "#" + xNode.Attributes["address"].Value;
                    //node.Tag = xNode.Attributes["email"].Value;
                    node.Name = xNode.Attributes["fname"].Value;
                    node.ImageKey = "Customers";
                }
                else if (xNode.Name == "contactGrp")
                {
                    node.Text = xNode.Attributes["name"].Value;
                    node.ImageKey = "ContactGrp";
                }
                else if (xNode.Name == "email")
                {
                    node.Text = xNode.Attributes["value"].Value;
                    node.ImageKey = "Email";
                }
                else if (xNode.Name == "FreezeGrp")
                {
                    node.Text = "~מוקפא~";
                    node.ImageKey = "FreezeGrp";
                }
                inTreeNode.Nodes.Add(node);
                tNode = inTreeNode.Nodes[i];
                AddNode(xNode, tNode);
            }
        }

        void treeView1_AfterCheck(object sender, TreeViewEventArgs e)
        {
            /*if (!node_list.Contains(e.Node))
            {
                if (e.Node.Equals(selectedTreeView.TopNode))
                    node_list.Add(selectedTreeView.TopNode);
                else
                    Utils.getEquivalentNodes(selectedTreeView.Nodes, ref node_list, e.Node);
                int firstCount = node_list.Count;
                for (int i = 0; i < firstCount; i++)
                {
                    node_list[i].Checked = e.Node.Checked;
                    makeCheckChildren(node_list[i]);
                }
                if (firstCount == 0)
                {
                    makeCheckChildren(e.Node);
                }
                node_list.Clear();
            }*/
            if (doneCheck)
            {
                callingNode = e.Node;
                doneCheck = false;
                treeView1.Cursor = Cursors.WaitCursor;
            }
         if (!node_list.Contains(e.Node))
            {
            makeCheckChildren(e.Node);
                        }
           // node_list.Clear();
        }

        public void makeCheckChildren(TreeNode parent)
        {

                if (parent.ImageKey == "Customers" && !callingNode.Equals(treeView1.TopNode))
                {
                    Utils.getEquivalentNodes(treeView1.Nodes, ref node_list, parent);
                    int firstCount = node_list.Count;
                    for (int i = 0; i < firstCount; i++)
                    {
                        node_list[i].Checked = parent.Checked;
                        for (int iCount = 0; iCount < node_list[i].Nodes.Count; iCount++)
                        {
                         //   node_list.Add(node_list[i].Nodes[iCount]);
                            node_list[i].Nodes[iCount].Checked = node_list[i].Checked;
                        }
                    }
                    if (firstCount == 0)
                    {
                        parent.Checked = parent.Parent.Checked;
                    }
                }
                else
                {
                    foreach (TreeNode node in parent.Nodes)
                    {
                        node_list.Add(node);
                        node.Checked = parent.Checked;
                        makeCheckChildren(node);
                    }
                }
            if (parent.Equals(callingNode))
            {
                doneCheck = true;
                treeView1.Cursor = Cursors.Arrow;
                node_list.Clear();
            }
            return;
        }

        void treeView1_ItemDrag(object sender, ItemDragEventArgs e)
        {
            DoDragDrop(e.Item, DragDropEffects.Move);
        }

        void treeView1_DragEnter(object sender, DragEventArgs e)
        {
            e.Effect = DragDropEffects.Move;
        }

        void treeView1_DragDrop(object sender, DragEventArgs e)
        {
            TreeNode NewNode;
            try
            {
                if (e.Data.GetDataPresent("System.Windows.Forms.TreeNode", false))
                {
                    Point pt = ((TreeView)sender).PointToClient(new Point(e.X, e.Y));
                    TreeNode DestinationNode = ((TreeView)sender).GetNodeAt(pt);
                    NewNode = (TreeNode)e.Data.GetData("System.Windows.Forms.TreeNode");
                    if (IsAllowedToMoveHere(NewNode, DestinationNode))
                    {
                        DestinationNode.Nodes.Add((TreeNode)NewNode.Clone());
                        DestinationNode.Expand();
                        //Remove Original Node
                        NewNode.Remove();
                    }
                }
            }
            catch
            {

            }
        }

        private bool IsAllowedToMoveHere(TreeNode destinationNode, TreeNode currentNode)
        {
            if (currentNode.Tag == null)
            {
                return IsHeigherInHierarchy(destinationNode, currentNode);
            }
            return false;
        }

        private bool IsHeigherInHierarchy(TreeNode destinationNode, TreeNode currentNode)
        {
            foreach (TreeNode node in destinationNode.Nodes)
            {
                foreach (TreeNode innerNode in destinationNode.Nodes)
                {
                    if (currentNode == innerNode)
                        return false;
                }
                if (currentNode == node)
                    return false;
            }

            return true;
        }

        private StreamWriter sr;
        /// <summary>
        /// Exports the given TreeView to Xml and returns a string containing all tags
        /// </summary>
        public void ExportToXml(string filename)
        {
            try
            {
                string path = Utils.GetXmlFileLocation(filename);
                using (MemoryStream stream = new MemoryStream())
                {
                    using (sr = new StreamWriter(stream, System.Text.Encoding.UTF8))
                    {
                        //Write the header
                        sr.WriteLine("<?xml version=\"1.0\" encoding=\"utf-8\" ?>");
                        //Write our root node
                        sr.WriteLine(string.Format("<contactGrp name=\"{0}\">", selectedTreeView.Nodes[0].Text));
                        foreach (TreeNode node in selectedTreeView.Nodes)
                        {

                            saveNode(node.Nodes);
                        }
                        //Close the root node
                        sr.WriteLine("</contactGrp>");
                        sr.Flush();

                        XmlDocument doc = new XmlDocument();
                        stream.Position = 0;
                        doc.Load(stream);

                        doc.PreserveWhitespace = true;
                        doc.Save(path);
                        sr.Close();
                        stream.Close();
                    }
                }
            }
            catch (System.UnauthorizedAccessException notAdminException)
            {
                MessageBox.Show("אנא הרץ את האפליקציה כמנהל");
            }
            catch (IOException exception)
            {
                //TODO: write better alert
                MessageBox.Show("הקובץ כרגע בשימוש");
            }
        }


        private void saveNode(TreeNodeCollection tnc)
        {
            foreach (TreeNode node in tnc)
            {
                //If we have child nodes, we'll write 
                //a parent node, then iterrate through
                //the children
                if (node.Nodes.Count > 0)
                {
                    //if (node.Tag == null)
                    if (node.ImageKey=="ContactGrp")
                    {
                        sr.WriteLine(
                           string.Format("<contactGrp name=\"{0}\">", node.Text.Replace("\"", "&quot;").Replace("'", "&apos;")));
                    }
                    else if (node.ImageKey == "Customers")
                    {
                        string email = (string)node.Tag;
                        string[] array1 = email.Split('#');
                        /*if (array1.GetLength(0)==0)
                           sr.WriteLine(
                           string.Format("<customer name=\"{0}\" detail=\"{1}\" cell=\"\" office=\"\">", node.Text,node.ToolTipText));
                        if (array1.GetLength(0) == 1)
                            sr.WriteLine("<customer name=\"" + node.Text + "\" detail=\"" + node.ToolTipText + "\" cell=\"" + array1[0] + "\" office=\"\">");
                         
                        if (array1.GetLength(0) == 2)*/
                        sr.WriteLine("<customer name=\"" + node.Text.Replace("\"", "&quot;").Replace("'", "&apos;") + "\" detail=\"" + node.ToolTipText.Replace("\"", "&quot;").Replace("'", "&apos;") + "\" cell=\"" + array1[0].Replace("\"", "&quot;").Replace("'", "&apos;") + "\" office=\"" + array1[1].Replace("\"", "&quot;").Replace("'", "&apos;") + "\" address=\"" + array1[2].Replace("\"", "&quot;").Replace("'", "&apos;") + "\" fname=\"" + node.Name.Replace("\"", "&quot;").Replace("'", "&apos;") + "\">");
                    }
                    else if (node.ImageKey == "Email")
                    {
                        sr.WriteLine(
                          string.Format("<email value=\"{0}\">", node.Text.Replace("\"", "&quot;").Replace("'", "&apos;")));
                    }
                    else if (node.ImageKey == "FreezeGrp")
                    {
                        sr.WriteLine(
                          string.Format("<FreezeGrp>"));
                    }
                    saveNode(node.Nodes);

                   // if (node.Tag == null)
                    if (node.ImageKey=="ContactGrp")
                    {
                        sr.WriteLine("</contactGrp>");
                    }
                    else if (node.ImageKey == "Customers")
                    {
                        sr.WriteLine("</customer>");
                    }
                    else if (node.ImageKey == "Email")
                    {
                        sr.WriteLine("</email>");
                    }
                    else if (node.ImageKey == "FreezeGrp")
                    {
                        sr.WriteLine("</FreezeGrp>");
                    }
                }
                else
                    //if (node.Tag == null)
                    if (node.ImageKey == "ContactGrp")
                    {
                        sr.WriteLine(
                           string.Format("<contactGrp name=\"{0}\"> </contactGrp>", node.Text.Replace("\"", "&quot;").Replace("'", "&apos;")));
                    }
                    else if (node.ImageKey=="Customers")
                    {
                        string email = (string)node.Tag;
                        String[] array1 = email.Split('#');
                       /* if (array1.GetLength(0) == 0)
                            sr.WriteLine(
                            string.Format("<customer name=\"{0}\" detail=\"{1}\" cell=\"\" office=\"\"></customer>", node.Text, node.ToolTipText));
                        if (array1.GetLength(0) == 1)
                            sr.WriteLine("<customer name=\"" + node.Text + "\" detail=\"" + node.ToolTipText + "\" cell=\"" + array1[0] + "\" office=\"\"></customer>");
                        if (array1.GetLength(0) == 2)
                        */
                        sr.WriteLine("<customer name=\"" + node.Text.Replace("\"", "&quot;").Replace("'", "&apos;") + "\" detail=\"" + node.ToolTipText.Replace("\"", "&quot;").Replace("'", "&apos;") + "\" cell=\"" + array1[0].Replace("\"", "&quot;").Replace("'", "&apos;") + "\" office=\"" + array1[1].Replace("\"", "&quot;").Replace("'", "&apos;") + "\" address=\"" + array1[2].Replace("\"", "&quot;").Replace("'", "&apos;") + "\" fname=\"" + node.Name.Replace("\"", "&quot;").Replace("'", "&apos;") + "\"></customer>");
                    }
                    else if (node.ImageKey == "Email")
                    {
                        sr.WriteLine(
                           string.Format("<email value=\"{0}\"> </email>", node.Text.Replace("\"", "&quot;").Replace("'", "&apos;")));
                    }
                    else if (node.ImageKey == "FreezeGrp")
                    {
                        sr.WriteLine(
                           string.Format("<FreezeGrp></FreezeGrp>"));
                    }
            }
        }

        List<Customer> customers;
        private void GetCheckedCustomers(TreeNodeCollection treeNodeCollection)
        {
            foreach (TreeNode treeNode in treeNodeCollection)
            {
                if (treeNode.Nodes.Count > 0)
                {
                    GetCheckedCustomers(treeNode.Nodes);
                    AddCheckedCustomersToList(customers, treeNode);
                }
                else
                {
                    AddCheckedCustomersToList(customers, treeNode);
                }
            }
        }

        internal List<Customer> GetCheckedCustomers()
        {
            customers = new List<Customer>();
            GetCheckedCustomers(treeView1.Nodes);
            return customers;
        }

        public void nothingChecked(TreeNode node,ref bool nChecked)
        {
            foreach (TreeNode node2 in node.Nodes)
            {
                if (node2.Checked || nChecked==false) {
                    nChecked = false;
                    return;
                }
                nothingChecked(node2,ref nChecked);
            }
        }

        void AddCheckedCustomersToList(List<Customer> customers, TreeNode node)
        {
            if (!node.Checked || node.ImageKey != "Email")
                return;
            Customer c =new Customer() {Name = node.Parent.Name, Email = node.Text,Fullpath=node.FullPath};
            bool contains = false;
            int i=0;
            while (!contains && i < customers.Count)
            {
                contains = (customers[i].Email == node.Text);
                i++;
            }
            if (!contains)
                customers.Add(c);
        }
    }
}
